﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace WpfControlDemo.ViewModels.Base
{
    /// <summary>
    /// 控件事件的绑定条件以及检查条件
    /// 备注：与RelayCommand类实现的效果是一样，只是类名不应，复制代码是不想改了而已。
    /// </summary>
    public class CommandBase : ICommand
    {
        #region 初始化
        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="execute"></param>
        public CommandBase()
        {

        }

        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="execute"></param>
        public CommandBase(Action<object> execute) : this(execute, null)
        {

        }

        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="execute">按钮点击事件委托</param>
        /// <param name="canExecute">用于设置控件是否可用委托</param>
        public CommandBase(Action<object> execute, Func<object, bool> canExecute)
        {
            DoExecute = execute; // 按钮点击事件委托
            DoCanExecute = canExecute; // 用于设置控件是否可用委托
        }
        #endregion

        #region 设置控件是否可用
        /// <summary>
        /// 通知：当前按钮检查可用条件     触发 一次CanExecute
        /// 需要触发这个事件，才能触发检查条件委托
        /// </summary>
        public event EventHandler CanExecuteChanged
        {
            // 检测可能更改要执行的命令的功能的条件时发生-这里会强制执行
            // 用于解决当属性变化时通知页面控件是否可用。
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        /// <summary>
        /// 用于设置控件是否可用委托
        /// </summary>
        public Func<object, bool> DoCanExecute { get; set; }

        /// <summary>
        /// 目的 就是触发一次CanExecuteChanged事件
        /// 触发事件的目的就是重新调用CanExecute方法
        /// </summary>
        public void DoCanExecuteChanged()
        {
            // 用于解决当属性变化时通知页面控件是否可用。
            //CanExecuteChanged?.Invoke(this, EventArgs.Empty);
        }

        /// <summary>
        /// 设置页面控件是否可用
        /// 通过返回值确定绑定当前命令实例的对象是否可用
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        public bool CanExecute(object parameter)
        {
            // 如果不想使用CanExecute方法控制页面按钮是否可用，可以直接返回true；
            // 否则页面按钮会是置灰状态
            if (DoCanExecute != null)
                return DoCanExecute(parameter);
            return true;
        }
        #endregion

        #region 控件执行命令
        /// <summary>
        /// 按钮点击事件委托
        /// </summary>
        public Action<object> DoExecute { get; set; }

        /// <summary>
        /// 执行过程 - 相当于ButtonClick 
        /// 页面控件触发之后执行什么样的逻辑
        /// </summary>
        /// <param name="parameter">这个参数是页面控件传递过来的，大多会将页面控件本身传递过来</param>
        /// <exception cref="NotImplementedException"></exception>
        public void Execute(object parameter)
        {
            // 加问号的原因是，如果为空的话这个委托方法不执行。
            // 我委托把一个点着引信的炸弹交给？，？就会拿着这个炸弹去，敌军阵营里，炸敌人，
            // 我委托把一个空盒子，交给？，？就会傻愣愣的一动不动。
            DoExecute?.Invoke(parameter);
        }
        #endregion
    }
}
